package com.asp.aspchain.core.util;


import com.asp.aspchain.core.ethereum.EthService;
import com.asp.aspchain.core.model.MgrContractModel;
import com.asp.aspchain.core.service.IMgrContractService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.StaticGasProvider;

import java.io.File;
import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by aspire on 2017/9/15.
 */
@Component
public class ContractUtil {

	@Value("${contract.keystorepath}")
	private String keystorepath;

	private Map<Integer, Object> contractMap = new HashMap<>();
	private Map<Integer, Credentials> credentialsMap = new HashMap<>();
	//生成的java文件放在指定目录
	private static final String packagePath = "com.asp.aspchain.core.contract.";
	@Autowired
	private IMgrContractService mgrContractService;
	@Autowired
	private EthService ethService;


	public Object getContract(Integer cid) throws Exception {
		//在hashMap里取出contract对象，如果是null，则加载对象
		Object object = contractMap.get(cid);
		if (object != null) {
			return object;
		}

		BigInteger GAS_PRICE = BigInteger.valueOf(22_000_000_000L);
		BigInteger GAS_LIMIT = BigInteger.valueOf(4_300_000);
		StaticGasProvider STATIC_GAS_PROVIDER =
				new StaticGasProvider(GAS_PRICE, GAS_LIMIT);
		Web3j web3j = ethService.initWeb3j();
		MgrContractModel mgrContractModel = mgrContractService.selectById(cid);
		//获得密钥文件
		Credentials credentials = getCredentialsByCid(cid);
		String contractAddress = mgrContractModel.getContractid();
		//数据读取生成的java文件名，放在指定的目录，用反射的方法获取构造函数，加载出对象
		String className = mgrContractModel.getClassname();
		Class<?> clazz = Class.forName(packagePath + className);
		Constructor con = clazz.getDeclaredConstructor(String.class, Web3j.class, Credentials.class, ContractGasProvider.class);
		//使其能访问private或者protect修饰的构造方法
		con.setAccessible(true);
		Object contract = con.newInstance(contractAddress, web3j, credentials, STATIC_GAS_PROVIDER);
		//HumanStandardToken_sol_HumanStandardToken contract = HumanStandardToken_sol_HumanStandardToken.load(contractAddress, web3j, credentials, STATIC_GAS_PROVIDER);

		//将对象放入hashMap里，以cid为key
		contractMap.put(cid, contract);
		return contract;
	}

	public Credentials getCredentialsByCid(Integer cid) throws Exception {
		//在map中取，取不到就加载，加载完毕后存入map中
		Credentials object = credentialsMap.get(cid);
		if (object != null) {
			return object;
		}
		MgrContractModel mgrContractModel = mgrContractService.selectById(cid);
		PathUtil pathUtil = new PathUtil(keystorepath);
		pathUtil.addPath(mgrContractModel.getCredentialsPath());
		String credentialsPath = pathUtil.toString();

		//System.out.println(credentialsPath);
		Credentials credentials = WalletUtils.loadCredentials("", credentialsPath);
		//存入map中
		credentialsMap.put(cid, credentials);
		return credentials;
	}

	/*private String getCredentialsPath(String accountid) {
		//获取根目录路径
		URL url = ContractUtil.class.getClassLoader().getResource("");
		String filepath = url.getFile();
		//获取根目录下所有文件
		File file = new File(filepath);
		File[] tempList = file.listFiles();
		//通过查找文件名包含accountid的文件获取密钥文件的路径
		for (int i = 0; i < tempList.length; i++) {
			if (tempList[i].isFile()) {
				if (tempList[i].getName().contains(accountid)) {
					return tempList[i].getPath();
				}
			}
		}
		return null;
	}*/

	public static void main(String[] args) {
		URL url = ContractUtil.class.getClassLoader().getResource("");
		String filepath = url.getFile();
		System.out.println(filepath);
		File file = new File(filepath);
		File[] tempList = file.listFiles();

		for (int i = 0; i < tempList.length; i++) {
			if (tempList[i].isFile()) {
				System.out.println("文件：" + tempList[i].getName());
			}
			if (tempList[i].isDirectory()) {
				System.out.println("文件夹：" + tempList[i]);
			}
		}

	}

}
